package com.netease.financial.module.web;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.View;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import com.netease.financial.R;
import com.netease.financial.base.customerservice.CustomerServiceHelper;
import com.netease.financial.base.web.JSBridge;
import com.netease.financial.base.web.JSBridgeHelper;
import com.netease.financial.base.web.JSInterface;
import com.netease.financial.base.web.WebStorageBridge;
import com.netease.financial.base.web.WebStoragePreferencesHelper;
import com.netease.financial.common.constant.Constants;
import com.netease.financial.common.util.HttpUtils;
import com.netease.financial.common.util.NetWorkUtils;
import com.netease.financial.common.util.NfsLog;
import com.netease.financial.common.util.StringUtils;
import com.netease.financial.common.util.ToastUtils;
import com.netease.financial.common.util.URIUtils;
import com.netease.financial.common.util.WebUtils;
import com.netease.financial.base.lockpattern.LockPatternHelper;
import com.netease.financial.module.browser.BrowserActivity;
import com.netease.financial.module.browser.MainBrowserActivity;
import com.netease.financial.module.main.MainActivity;
import com.tendcloud.tenddata.TCAgent;

import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.netease.financial.base.web.WebStoragePreferencesHelper.KEY_LOCAL_STORAGE_USER_ID;
import static com.netease.financial.base.web.WebStoragePreferencesHelper.KEY_SESSION_STORAGE_HISTORIES;

/**
 * Created by wyf on 6/10/15.
 */
public class WebViewHelper {

    // 各个tab页的初始地址集合
    private static final Map<String, Integer> sInitialUrlMap;

    static {
        sInitialUrlMap = new HashMap<>();
        sInitialUrlMap.put(Constants.getHomeUrl(), MainActivity.TAB_POSITION_HOME);
        sInitialUrlMap.put(Constants.getProductUrl(), MainActivity.TAB_POSITION_PRODUCT);
        sInitialUrlMap.put(Constants.getInformationUrl(), MainActivity.TAB_POSITION_INFORMATION);
        sInitialUrlMap.put(Constants.getAssetUrl(), MainActivity.TAB_POSITION_ASSET);
        sInitialUrlMap.put(Constants.getAccountUrl(), MainActivity.TAB_POSITION_ACCOUNT);
    }

    private static final String TAG = WebViewHelper.class.getSimpleName();

    // 自定义错误处理界面
    private static final String ERROR_URL = "file:///android_asset/web/error.html";

    private Context mContext;
    private WebViewTabFragment mFragment;
    private WebView mWebView;
    private String mUrl = "";
    private FinancialWebViewClient mWebViewClient;

    private JSBridgeHelper mJsbHelper;
    private WebViewTabFragment.OnFragmentInteractionListener mOnFragmentInteractionListener;

    public WebViewHelper(Context context, WebViewTabFragment fragment, WebView webView, String url) {
        mContext = context;
        mFragment = fragment;
        mWebView = webView;
        mUrl = url;

        initWebViewSettings(mWebView);
        setWebChromeClient(mWebView);
        setWebViewClient(mWebView);
        setOnKeyListener(mWebView);
//        setOnLongClickListener(mWebView);
        mJsbHelper = JSBridgeHelper.newInstance(mWebView);
        mJsbHelper.registerCommandForJs();
        addWebActionListener(JSInterface.REQUEST_JS_REFRESH_PAGE, mWebViewClient);

        NfsLog.d(TAG, "mUrl = " + mUrl);
        mWebViewClient.loadUrl(mUrl);
    }

    public void setOnFragmentInteractionListener(WebViewTabFragment.OnFragmentInteractionListener listener) {
        mOnFragmentInteractionListener = listener;
    }

    public void addWebActionListener(String request, JSInterface.WebActionListener listener) {
        mJsbHelper.addWebActionListener(request, listener);
    }

    @SuppressLint("SetJavaScriptEnabled")
    private void initWebViewSettings(WebView webView) {
        WebSettings webSettings = webView.getSettings();
        webSettings.setJavaScriptEnabled(true);

        // 在user agent中增加应用信息，服务器端可以从user agent中获取此信息
        String defaultUserAgent = webSettings.getUserAgentString();
        String extraHeader = HttpUtils.getExtraHeader(mContext);
        webSettings.setUserAgentString(defaultUserAgent + extraHeader);

        webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
        /***打开本地缓存提供JS调用**/
        webSettings.setDomStorageEnabled(true);
        // Set cache size to 8 mb by default. should be more than enough
//        webSettings.setAppCacheMaxSize(1024*1024*8);

        //让WebView 支持ViewPort的缩放 (改方式只在外页面使用!)
//        webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
//        webSettings.setUseWideViewPort(true);


        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            WebView.setWebContentsDebuggingEnabled(NfsLog.DEBUG_MODE);
        }
    }

    private boolean isTopPage(String url) {
        if (isInitialPage(url)) {
            return true;
        }

        return !mWebView.canGoBack() && ERROR_URL.equals(url);

    }

    public boolean isInitialPage(String url) {
        if (TextUtils.isEmpty(url)) {
            return false;
        }
        return sInitialUrlMap.containsKey(WebUtils.getUrlByRemoveParams(url));
    }

    private void setWebViewClient(final WebView webView) {
        mWebViewClient = new FinancialWebViewClient();
        webView.setWebViewClient(mWebViewClient);
    }

    private void setWebChromeClient(final WebView webView) {
        webView.setWebChromeClient(new WebChromeClient() {
            @Override
            public void onProgressChanged(WebView view, int newProgress) {
                super.onProgressChanged(view, newProgress);
            }

            @Override
            public void onReceivedTitle(WebView view, String title) {
                super.onReceivedTitle(view, title);
            }

        });
    }

    private void showBottomTabWidget(boolean show) {
        if (mOnFragmentInteractionListener != null) {
            mOnFragmentInteractionListener.showBottomTabWidget(show);
        }
    }

    public void setTitle() {
        if (mOnFragmentInteractionListener != null) {
            String title;
            if (mWebViewClient.isErrorPage()) {
                title = mContext.getResources().getString(R.string.app_name);
            } else {
                title = mWebView.getTitle();
            }
            if (TextUtils.isEmpty(title) || title.contains("http") || title.contains("192")
                    || title.contains("com") || title.contains("html")) {
                return;
            }
            mOnFragmentInteractionListener.setNavigationTitle(title);
        }
    }

    private void showNavigationBackOptionItem(boolean show) {
        if (mOnFragmentInteractionListener != null) {
            if (show) {
                mOnFragmentInteractionListener.showNavBackItem();
            } else {
                mOnFragmentInteractionListener.hideNavBackItem();
            }
        }
    }

    private void refreshCurrentTabBadgeView() {
        if (mOnFragmentInteractionListener != null) {
            mFragment.refreshTabBadgeView();
        }
    }

    private void setOnKeyListener(final WebView webView) {
        webView.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                if (event.getAction() == KeyEvent.ACTION_DOWN) {
                    if (keyCode == KeyEvent.KEYCODE_BACK) {
                        NfsLog.d(TAG, "webView.getUrl = " + webView.getUrl());
                        NfsLog.d(TAG, "webView.canGoBack() = " + webView.canGoBack());

                        if (webView.getUrl() != null && !webView.getUrl().contains(WebUtils.getUrlByRemoveParams(mUrl))) {
                            executeCustomGoBack();
                            return true;
                        }
                    }
                }
                return false;
            }
        });
    }

    public void handleGoBackEvent() {
        executeCustomGoBack();
    }

    private void executeCustomGoBack() {
        if (mWebView.getUrl().indexOf("f=def") >= 0) {
            mWebView.goBack();
            return;
        }
        mJsbHelper.getSessionStorageItem(KEY_SESSION_STORAGE_HISTORIES, new WebStorageBridge.CallBack() {
            @Override
            public void onItemCallBack(String itemName, String itemValue) {
                NfsLog.d(TAG, "getSessionStorageItem.onItemCallBack.itemName = " + itemName + ", itemValue = " + itemValue);
                final String urlForBack = getUrlForBack(itemValue);
                if (!TextUtils.isEmpty(urlForBack)) {
                    mWebView.post(new Runnable() {
                        @Override
                        public void run() {
                            mWebView.loadUrl(urlForBack);
                        }
                    });
                }
            }
        });
    }

    // 向web session storage中存储数据
    private void setValueToSessionStorage(final String key, final String value) {
        mWebView.post(new Runnable() {
            @Override
            public void run() {
                mJsbHelper.saveSessionStorageItem(key, value);
            }
        });
    }

    // 获取用户点击返回按钮时，应该跳转到的页面地址
    private String getUrlForBack(String historyUrls) {
        String[] historyUrlArray = getHistoryUrlList(historyUrls);
        String urlForBack = null;
        if (historyUrlArray != null && historyUrlArray.length > 0) {
            if (historyUrlArray.length == 0)
                return historyUrlArray[0];
            List<String> historyUrlList = getArrayList(historyUrlArray);
            historyUrlList.remove(historyUrlList.size() - 1);

            urlForBack = historyUrlList.get(historyUrlList.size() - 1);

            // 添加标识，以告诉前端当前页面是从其他页面返回,所以不需要加入历史数据栈中
            urlForBack = URIUtils.appendUriQuietly(urlForBack, "f=2");
            NfsLog.d(TAG, "mutableHistoryUrlList.size() ==================" + historyUrlList.size());

            saveHistoryUrlArray(historyUrlList);
        }

        NfsLog.d(TAG, "p_getUrlForBack==================" + urlForBack);
        return urlForBack;
    }

    @NonNull
    private List<String> getArrayList(String[] historyUrlArray) {
        List<String> stringList = new ArrayList<>();
        for (String str : historyUrlArray) {
            stringList.add(str);
        }
        return stringList;
    }

    // 从web session storage中获取自定义的历史记录
    String[] getHistoryUrlList(String historyUrls) {
        String[] historyUrlList = null;
        if (historyUrls != null) {
            historyUrlList = historyUrls.split(",");
        }

        return historyUrlList;
    }

    // 保存自定义的web浏览历史记录到web session storage
    private void saveHistoryUrlArray(List<String> historyUrlList) {
        String historyUrls = StringUtils.join(historyUrlList.toArray(), ",");
        NfsLog.d(TAG, "p_saveHistoryUrlArray.historyUrls == " + historyUrls);
        setValueToSessionStorage(KEY_SESSION_STORAGE_HISTORIES, historyUrls);
    }

    private void setOnLongClickListener(final WebView webView) {
        // 屏蔽掉长按事件 因为WebView长按时将会调用系统的复制控件
        webView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                return true;
            }
        });
    }

    private void hideOptionMenu() {
        if (mOnFragmentInteractionListener != null) {
            mOnFragmentInteractionListener.hideOptionMenu();
        }
    }

    private void setCurrentTabAccordingToUrl(String url) {
        if (isInitialPage(url) && !url.contains(WebUtils.getUrlByRemoveParams(mUrl))) {
            if (mOnFragmentInteractionListener != null) {
                int tabPosition = sInitialUrlMap.get(WebUtils.getUrlByRemoveParams(url));
                NfsLog.d(TAG, "tabPosition = " + tabPosition);
                mOnFragmentInteractionListener.setCurrentTab(tabPosition);
            }
        }
    }

    private boolean isFortuneClubDomain(String url) {
        return !TextUtils.isEmpty(url) && url.contains(Constants.getDomain());
    }

    private boolean shouldJumpToOut(String url) {
        Uri uri = Uri.parse(url);
        String params = uri.getEncodedQuery();
        if (TextUtils.isEmpty(params))
            return false;
        if (params.contains("target=nologin"))
            return true;
        if (params.contains("target=login")) {
            return true;
        }
        return false;
//        return !TextUtils.isEmpty(params)&&params.contains("target=out")&&!TextUtils.isEmpty(WebStoragePreferencesHelper.getLocalStorageItem(WebStoragePreferencesHelper.KEY_LOCAL_STORAGE_ACCESS_TOKEN));
    }

    public void handleLocalStorageItems() {
        saveLocalStorageItem(WebStoragePreferencesHelper.KEY_LOCAL_STORAGE_ACCESS_TOKEN);
        saveLocalStorageItem(WebStoragePreferencesHelper.KEY_LOCAL_STORAGE_CLIENT_ID);
        saveLocalStorageItem(WebStoragePreferencesHelper.KEY_LOCAL_STORAGE_HEAD_PORTRAIT_URL);
        mJsbHelper.getLocalStorageItem(KEY_LOCAL_STORAGE_USER_ID, new WebStorageBridge.CallBack() {
            @Override
            public void onItemCallBack(String itemName, String itemValue) {
                WebStoragePreferencesHelper.saveLocalStorageItem(itemName, itemValue);
                CustomerServiceHelper.setUserId(itemValue);
                LockPatternHelper.setUserId(itemValue);
            }
        });
        mJsbHelper.getLocalStorageItem(WebStoragePreferencesHelper.KEY_LOCAL_STORAGE_CLIENT_ID, new WebStorageBridge.CallBack() {
            @Override
            public void onItemCallBack(String itemName, String itemValue) {
                WebStoragePreferencesHelper.saveLocalStorageItem(itemName, itemValue);
                LockPatternHelper.setClientId(itemValue);
            }
        });
    }

    private void saveLocalStorageItem(String itemName) {
        mJsbHelper.getLocalStorageItem(itemName, mSaveLocalStorageItemCallBack);
    }

    private WebStorageBridge.CallBack mSaveLocalStorageItemCallBack = new WebStorageBridge.CallBack() {
        @Override
        public void onItemCallBack(String itemName, String itemValue) {
            ToastUtils.showDebugToast(mContext, "itemValue = " + itemValue);
            WebStoragePreferencesHelper.saveLocalStorageItem(itemName, itemValue);
        }
    };

    private final class FinancialWebViewClient extends WebViewClient implements JSInterface.WebActionListener {
        private boolean shouldClearHistory = false;
        private boolean shouldLoadFailingUrl = false;
        private boolean shouldLoadErrorPage = false;
        private String mFailingUrl;
        private boolean mIsErrorPage;

        public boolean isErrorPage() {
            return mIsErrorPage;
        }

        public void loadUrl(String mUrl) {
            if (NetWorkUtils.isNetworkAvailable(mContext)) {
                mWebView.loadUrl(mUrl);
            } else {
                mFailingUrl = mUrl;
                mWebView.loadUrl(ERROR_URL);
            }
        }

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            hideOptionMenu();
            TCAgent.onPageEnd(mContext, view.getTitle());
            mIsErrorPage = false;
            mJsbHelper.setCurrentUrl(url);
            super.onPageStarted(view, url, favicon);
        }

        @Override
        public void onReceivedError(final WebView view, int errorCode, String description, String failingUrl) {
            mIsErrorPage = true;
//                mFailingUrl = failingUrl;
            super.onReceivedError(view, errorCode, description, failingUrl);
        }

        @Override
        public void onPageFinished(final WebView view, String url) {
            NfsLog.d(TAG, "onPageFinished.url:" + url);

            handleLocalStorageItems();
            trackUser(url);
            if (shouldClearHistory) {
                view.clearHistory();
                shouldClearHistory = false;
            } else if (shouldLoadFailingUrl) {
                view.loadUrl(mFailingUrl);
                shouldLoadFailingUrl = false;
            } else if (shouldLoadErrorPage) {
                view.loadUrl(ERROR_URL);
                mIsErrorPage = true;
                shouldClearHistory = false;
            }

            TCAgent.onPageStart(mContext, view.getTitle());
            if (mFragment.isVisible()) {
                handleOnVisiblePageFinished(view, url);
            }
            super.onPageFinished(view, url);
        }

        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            // 如果是拨号或者邮件,则调用系统的拨号和邮件相关功能进行处理
            if (url.startsWith("tel:") || url.startsWith("mailto:")) {//|| !isFortuneClubDomain(url)) {
                Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
                mContext.startActivity(intent);
                return true;
            }
            // 如果是其他非富聪社的地址，则调用内部浏览器进行处理
            if (!isFortuneClubDomain(url) || shouldJumpToOut(url)) {
//                Uri uri = Uri.parse(url);
//                String params = uri.getEncodedQuery();
//                if (!TextUtils.isEmpty(params) && params.contains("target=login") &&
//                        TextUtils.isEmpty(WebStoragePreferencesHelper.getLocalStorageItem(WebStoragePreferencesHelper.KEY_LOCAL_STORAGE_ACCESS_TOKEN))){
//                    url = Constants.getDomain() + "/Dashboard/user/login.html?flow=loginNormal";
//                } else {
                Intent intent = new Intent(mContext, MainBrowserActivity.class);
                intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
                intent.putExtra(BrowserActivity.EXTRA_BROWSER_URL, "fc://" + url);
                mContext.startActivity(intent);
                return true;
//                }
            }
            if (isInitialPage(url) && !url.contains(mUrl)) {
                view.loadUrl(mUrl);
                setCurrentTabAccordingToUrl(url);
                return true;
            }
            if (!NetWorkUtils.isNetworkAvailable(mContext)) {
                mFailingUrl = url;
                view.loadUrl(ERROR_URL);
                return true;
            }
            return super.shouldOverrideUrlLoading(view, url);
        }

        @Override
        public void onRequest(JSBridge.Command cmd) {
            if (JSInterface.REQUEST_JS_REFRESH_PAGE.equals(cmd.getName())) {
                mWebView.post(new Runnable() {
                    @Override
                    public void run() {
                        FinancialWebViewClient.this.reloadInErrorPage();
                    }
                });
            }
        }

        public void reloadInErrorPage() {
            if (NetWorkUtils.isNetworkAvailable(mContext)) {
                if (mWebView.canGoBack()) {
                    shouldLoadFailingUrl = true;
                    mWebView.goBack();
                } else {
                    shouldClearHistory = true;
                    mWebView.loadUrl(mFailingUrl);
                }
            } else {
                mWebView.reload();
            }
        }

//        public void reload() {
//
//            if (ERROR_URL.equals(mWebView.getUrl())) {
//                reloadInErrorPage();
//                return;
//            }
//
//            if (NetWorkUtils.isNetworkAvailable(mContext)) {
//                mWebView.reload();
//                return;
//            }
//
//            mFailingUrl = mWebView.getUrl();
//            if (mWebView.canGoBack()) {
//                shouldLoadErrorPage = true;
//                mWebView.goBack();
//            } else {
//                shouldClearHistory = true;
//                mWebView.loadUrl(ERROR_URL);
//            }
//        }
    }

    // cloud business service, track user
    private void trackUser(String url) {
        CustomerServiceHelper.trackUserAccess(url, mWebView.getTitle());
    }

    private void handleOnVisiblePageFinished(WebView view, String url) {
        boolean isTopPage = isTopPage(url);
        showNavigationBackOptionItem(!isTopPage);
        showBottomTabWidget(isTopPage);

        if (isTopPage) {
            refreshCurrentTabBadgeView();
            view.clearHistory();
        }
        setTitle();

        if (WebStoragePreferencesHelper.isUserNeedLogout()) {
            WebUtils.removeLocalStorageItem(mWebView, WebStoragePreferencesHelper.KEY_LOCAL_STORAGE_ACCESS_TOKEN);
            WebUtils.removeLocalStorageItem(mWebView, WebStoragePreferencesHelper.KEY_LOCAL_STORAGE_USER_ID);
            handleLocalStorageItems();
            WebStoragePreferencesHelper.setUserNeedLogout(false);
            mWebView.reload();
        }
    }

    public void onHiddenChanged(boolean hidden) {
        if (!hidden) {
            handleOnVisiblePageFinished(mWebView, mUrl);
            dispatchPageShowEvent();
        }
    }

    private void dispatchPageShowEvent() {
        JSONObject params = new JSONObject();
        mJsbHelper.executeJsFunction(JSInterface.REQUEST_NATIVE_RESUME, params, new JSBridge.Callback() {
            @Override
            public void onComplete(JSBridge.Command command, JSONObject result) {
                NfsLog.d(TAG, "onComplete:" + command.toString());
            }
        });
    }

}
